/*
 *  SoundInfo.h
 *  SoundEngine
 *
 *   Created by jobs mac on 09-5-7.
 *   Copyright __MyCompanyName__ 2009. All rights reserved.
 *
 */

#import <UIKit/UIKit.h>
#import <OpenAL/al.h>
#import <OpenAL/alc.h>
#import <string>
#import "vorbis/vorbisfile.h"
#import <pthread.h>
#import <AudioToolbox/AudioToolbox.h>

class CSoundBase {
public:
	enum {
		SOUND_TYPE_UNKNOWN = 0,
		SOUND_TYPE_WAV,
		SOUND_TYPE_CAF,
		SOUND_TYPE_OGG,
	};	
public:	
	CSoundBase():m_bLooping(false),m_i4State(AL_INITIAL)
	{}
	virtual ~CSoundBase(){}
	
public:
	//	播放
	virtual	void Play(bool bLooping = false){}
	//	停止
	virtual void Stop(){}
	//	暂停
	virtual void Pause(){}
	//	获取状态
	virtual int State(){return 0;}
	//	初始化
	virtual int Init(const char *szFileName){return 0;}
	//	释放资源
	virtual void Release(){}
	//	设置音量
	inline void SetVolume(float fVolume)
	{
		alSourcef(m_u4Source, AL_GAIN, fVolume);
	}
	//	获取最后一次状态
	inline int LastState(){
		return m_i4State;
	}
	//	是否循环播放
	inline bool IsLooping(){
		return m_bLooping;
	}
	
	virtual void Update(float dt){}
	
	static CSoundBase *CreateSound(const char *szFileName, bool bQueue = false);

protected:
	ALuint	m_u4Source;
	ALint	m_i4State;
	bool	m_bLooping;
};

class CSoundPCM : public CSoundBase {
public:
	CSoundPCM();
	virtual ~CSoundPCM();
	
	virtual	void Play(bool bLooping = false);
	virtual void Stop();
	virtual void Pause();
	virtual int State();
	virtual int Init(const char *szFileName);
	virtual void Release();

private:
	int _initBuffer(const char *szFileName, ALuint &u4Buffer);
	int _initSource(ALuint &u4Source);
	
private:
	ALuint	m_u4Buffer;
};

class CSoundPCMQueue : public CSoundBase {
private:
	enum {
		MAX_BUFFER_NUM = 5,
	};
public:
	CSoundPCMQueue();
	virtual ~CSoundPCMQueue();
	
	virtual	void Play(bool bLooping = false);
	virtual void Stop();
	virtual void Pause();
	virtual int State();
	virtual int Init(const char *szFileName);
	virtual void Release();
	virtual void Update(float dt);
	
private:
	int _initBuffer(const char *szFileName, ALuint *u4Buffers, int &i4NumberOfBuffer);
	int _initSource(ALuint &u4Source);
	bool _ReadAudioData(ALuint &u4Buffer, AudioFileID afid, int *pi4Offset, int i4TotalSize, int i4Format, int i4Rate);
	bool _OpenAudioFile(CFURLRef inFileURL, AudioFileID *outAudioFileID, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei *outSampleRate);
private:
	unsigned int	m_u4Buffers[MAX_BUFFER_NUM];
	AudioFileID		m_AudioFileID;
	int				m_i4Size, 
					m_i4Format, 
					m_i4Rate,
					m_i4Offset;
	bool			m_bEnded;
};

class CSoundOgg : public CSoundBase {
public:

	enum {
		OGG_THREAD_RUNING = 0,
		OGG_THREAD_STOPING,
		OGG_THREAD_STOPPED,
	};
	
	enum {
		MAX_BUFFER_NUM = 10,
	};
	
public:
	CSoundOgg();
	virtual ~CSoundOgg();
	
	virtual	void Play(bool bLooping = false);
	virtual void Stop();
	virtual void Pause();
	virtual int State();
	virtual int Init(const char *szFileName);
	virtual void Release();
	virtual void Update(float dt);

private:
	static void *PlayThread( void *_ptr );
	
	int _GetBufferStream( unsigned int u4Buffer );
	int _LoadOgg(const char *szFileName, unsigned int *u4Buffers, int i4BufferNum);
	int _UpdateBufferStream();
	int _ResourceFree();
private:
	int				m_i4ThreadState;
	int				m_priority;
	
	pthread_t		m_thread;
	unsigned int	m_thread_hdl;
	
	unsigned int	m_u4Buffers[MAX_BUFFER_NUM];
	
	unsigned int	m_u4Curr;
	
	unsigned int	m_u4Format;
	
	unsigned int	m_u4Size;
	unsigned int	m_u4Rate;
	
	char			*m_cData;
	unsigned int	m_u4NumberOfBuffer;
	bool			m_bEnded;
	
	vorbis_info		*m_pinfo;
	OggVorbis_File  m_OggFile;
};

